angular.module('ui.bootstrap.buttons', [])

    .constant('buttonConfig', {
      activeClass: 'active',
      toggleEvent: 'click'
    })

    .controller('ButtonsController', ['buttonConfig', function(buttonConfig) {
      this.activeClass = buttonConfig.activeClass || 'active';
      this.toggleEvent = buttonConfig.toggleEvent || 'click';
    }])

    .directive('btnRadio', function () {
      return {
        require: ['btnRadio', 'ngModel'],
        controller: 'ButtonsController',
        link: function (scope, element, attrs, ctrls) {
          var buttonsCtrl = ctrls[0], ngModelCtrl = ctrls[1];

          //model -> UI
          ngModelCtrl.$render = function () {
            element.toggleClass(buttonsCtrl.activeClass, angular.equals(ngModelCtrl.$modelValue, scope.$eval(attrs.btnRadio)));
          };

          //ui->model
          element.bind(buttonsCtrl.toggleEvent, function () {
            var isActive = element.hasClass(buttonsCtrl.activeClass);

            if (!isActive || angular.isDefined(attrs.uncheckable)) {
              scope.$apply(function () {
                ngModelCtrl.$setViewValue(isActive ? null : scope.$eval(attrs.btnRadio));
                ngModelCtrl.$render();
              });
            }
          });
        }
      };
    })

    .directive('btnCheckbox', function () {
      return {
        require: ['btnCheckbox', 'ngModel'],
        controller: 'ButtonsController',
        link: function (scope, element, attrs, ctrls) {
          var buttonsCtrl = ctrls[0], ngModelCtrl = ctrls[1];

          function getTrueValue() {
            return getCheckboxValue(attrs.btnCheckboxTrue, true);
          }

          function getFalseValue() {
            return getCheckboxValue(attrs.btnCheckboxFalse, false);
          }

          function getCheckboxValue(attributeValue, defaultValue) {
            var val = scope.$eval(attributeValue);
            return angular.isDefined(val) ? val : defaultValue;
          }

          //model -> UI
          ngModelCtrl.$render = function () {
            element.toggleClass(buttonsCtrl.activeClass, angular.equals(ngModelCtrl.$modelValue, getTrueValue()));
          };

          //ui->model
          element.bind(buttonsCtrl.toggleEvent, function () {
            scope.$apply(function () {
              ngModelCtrl.$setViewValue(element.hasClass(buttonsCtrl.activeClass) ? getFalseValue() : getTrueValue());
              ngModelCtrl.$render();
            });
          });
        }
      };
    });